<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class AIChatController extends Controller
{
    /**
     * 流式对话并保存上下文
     * 
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\StreamedResponse
     */
    protected $lastResponseText = '';
    public function chatWithMemory(Request $request)
{
    $validated = $request->validate([
        'message' => 'required|string|max:1000',
        'token' => 'required|string'
    ]);

    $userId = auth()->id();
    $cacheKey = "ai_chat_context_{$userId}";

    // 获取历史上下文
    $context = Cache::get($cacheKey, []);
    
    // 构建完整提示词（包含历史对话）
    $prompt = $this->buildPrompt($validated['message'], $context);
    Log::debug('提示词', [
        'prompt' => $prompt
    ]);
    
    // 流式调用百炼API
    return response()->stream(function() use ($prompt, $validated, $cacheKey, &$context) {
        $fullResponse = '';
        $this->lastResponseText = ''; // 重置状态
        $this->sseBuffer = '';
        $this->sseEvents = [];
        
        try {
            // 记录API调用开始
            Log::debug('调用百炼API', [
                'endpoint' => config('bailian.endpoint'),
                'prompt_length' => strlen($prompt)
            ]);
            
            $token = $validated['token'];
            $response = Http::timeout(30)
                ->withHeaders($this->getHeaders())
                ->withOptions(['stream' => true])
                ->post(config('bailian.endpoint'), $this->getRequestBody($prompt, $token));
            
            // 记录API响应状态
            Log::debug('百炼API响应状态', [
                'status' => $response->status(),
                'headers' => $response->headers()
            ]);
            
            $body = $response->toPsrResponse()->getBody();
            $startTime = time();
            $maxExecutionTime = 60; 

            while (!$body->eof() ) {
                $chunk = $body->read(1024);
                $text = $this->parseResponseChunk($chunk);
                
                Log::debug('读取数据块', [
                    'chunk_size' => strlen($chunk),
                    'is_eof' => $body->eof(),
                    'buffer_size' => strlen($this->sseBuffer)
                ]);
                
                if ($text) {
                    echo $text;
                    ob_flush();
                    flush();
                    $fullResponse .= $text;
                }
                usleep(1000); // 减少CPU占用，避免过快读取
            }

            // 流结束后处理剩余缓冲区
            if ($this->sseBuffer) {
                $text = $this->parseResponseChunk("\n\n"); // 强制结束最后事件
                if ($text) {
                    echo $text;
                    ob_flush();
                    flush();
                    $fullResponse .= $text;
                }
            }
            
            // 记录完整响应
            Log::info('AI对话完成', [
                'full_response_length' => strlen($fullResponse),
                'response_sample' => mb_substr($fullResponse, 0, 200)
            ]);
            
            // 只有在有响应内容时才更新上下文
            if (!empty($fullResponse)) {
                $context[] = ['user' => $validated['message'], 'ai' => $fullResponse];
                Cache::put($cacheKey, $context, now()->addHours(1));
            }
            
        } catch (\Exception $e) {
            // 记录异常
            Log::error('流式响应异常', [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);
            
            // 发送错误信息给客户端
            echo "【系统错误】服务暂时不可用，请稍后再试";
        }
        
        if (empty($fullResponse)) {
            Log::error('百炼API返回空响应', [
                'prompt' => mb_substr($prompt, 0, 100),
                'response_headers' => $response->headers()
            ]);
            echo "【服务异常】未获取到AI响应，请稍后重试";
        }
    }, 200, [
        'Content-Type' => 'text/event-stream',
        'Cache-Control' => 'no-cache',
        'X-Accel-Buffering' => 'no'
    ]);
}

    /**
     * 构建包含上下文的提示词
     */
    private function buildPrompt(string $message, array $context): string
{
    $prompt = '你是一个记账智能客服助手，请用中文回答用户问题。每次用户询问账单信息时，都必须重新查询最新的数据。\n\n';
    $maxLength = 4000; // 设置最大上下文长度
    
    foreach ($context as $turn) {
        $newSegment = "用户: {$turn['user']}\nAI: {$turn['ai']}\n";
        // 检查长度限制
        if (strlen($prompt) + strlen($newSegment) > $maxLength) break;
        $prompt .= $newSegment;
    }
    
    $prompt .= "用户: {$message}\nAI:";
    Log::debug('上下文长度', [
        'length' => strlen($prompt),
        'turns' => count($context)
    ]);
    return $prompt;
}

    /**
     * 获取百炼API请求头
     */
    private function getHeaders(): array
    {
        return [
            'Authorization' => 'Bearer ' . config('bailian.api_key'),
            'Content-Type' => 'application/json',
            'X-DashScope-SSE' => 'enable'
        ];
    }

    /**
     * 构建请求体
     */
    private function getRequestBody(string $prompt, string $token): array
    {
        Log::debug('鉴权参数',  ['token' => $token]);
        return [
            'input' => [
                'prompt' => $prompt,
                'biz_params' => [
                'user_defined_params' => [
                    config('bailian.plugin_id') => [
                        'year' => 2025            
                        ]
                    ],
                'user_defined_tokens' => [
                    config('bailian.plugin_id') => [
                        'user_token' => $token
                    ]
                ]
                ]
            ],
            // 'parameters' => ['incremental_output' => true],
            'debug' => new \stdClass()
        ];
    }

    /**
     * 解析响应块
     */

     // 添加类属性保存解析状态
    protected $sseBuffer = '';
    protected $sseEvents = [];
    private function parseResponseChunk(string $chunk): ?string
{
    Log::debug('原始响应块', ['chunk' => base64_encode($chunk)]);
    $this->sseBuffer .= $chunk;
    $newText = '';
    $latestText = '';
    
    // 分割完整事件 (以两个换行符为分隔符)
    while (($pos = strpos($this->sseBuffer, "\n\n")) !== false) {
        $rawEvent = substr($this->sseBuffer, 0, $pos);
        $this->sseBuffer = substr($this->sseBuffer, $pos + 2);
        
        $eventData = $this->parseSseEvent($rawEvent);
        if ($eventData) {
            // 检查是否有完整的文本（finish_reason为stop的情况）
            if (isset($eventData['output']['finish_reason']) && $eventData['output']['finish_reason'] === 'stop' && !empty($eventData['output']['text'])) {
                $latestText = $eventData['output']['text'];
            } 
            // 增量更新的情况
            elseif (isset($eventData['output']['text'])) {
                $latestText = $eventData['output']['text'];
            }
        }
    }
    
    if (!empty($latestText) && strlen($latestText) > strlen($this->lastResponseText)) {
        $newText = substr($latestText, strlen($this->lastResponseText));
        $this->lastResponseText = $latestText;
        return $newText;
    }
    
    return $newText ?: null;
}


private function parseSseEvent(string $rawEvent): ?array
{
    $event = ['data' => ''];
    $lines = explode("\n", trim($rawEvent));
    
    foreach ($lines as $line) {
        // 解析SSE字段 (field: value)
        if (preg_match('/^(\w+):\s*(.+)$/', $line, $matches)) {
            $field = $matches[1];
            $value = trim($matches[2]);
            
            if ($field === 'data') {
                $event['data'] .= $value;
            } else {
                $event[$field] = $value;
            }
        }
    }
    
    // 尝试解析JSON数据
    if (!empty($event['data'])) {
        // 检查JSON数据是否可能是完整的（简单检查括号匹配）
        if ($this->isJsonComplete($event['data'])) {
            $data = json_decode($event['data'], true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $data;
            }
        
        Log::warning('SSE数据解析失败', [
            'error' => json_last_error_msg(),
            'raw_data' => $event['data']
        ]);
    }
    }
    return null;
    }
    // 添加检查JSON完整性的方法
private function isJsonComplete(string $jsonString): bool
{
    // 简单检查：确保开头和结尾有匹配的括号
    $jsonString = trim($jsonString);
    if (empty($jsonString)) {
        return false;
    }
    
    $firstChar = $jsonString[0];
    $lastChar = substr($jsonString, -1);
    
    // 检查基本的括号匹配
    if (($firstChar === '{' && $lastChar === '}') || 
        ($firstChar === '[' && $lastChar === ']')) {
        // 进行完整的JSON语法检查
        json_decode($jsonString);
        return json_last_error() === JSON_ERROR_NONE;
    }
    
    return false;
}
}